﻿using System;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
using System.Xml;
using QRCoder;
using System.Collections.Generic;
using System.Net.NetworkInformation;
using System.Net;
using System.Text;
using Newtonsoft.Json.Linq;
using System.Threading;
using System.Web;
using System.Web.Script.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Microsoft.Win32;
using System.Runtime.InteropServices;

namespace WindowsFormsApp2
{
    public partial class Form1 : Form
    {
        /// <summary>
        /// 可执行文件(程序)所在的文件夹路径 带"\"
        /// </summary>
        string exePath = "";
        /// <summary>
        /// 临时存储ofd文件和其解压文件的文件夹名称
        /// </summary>
        const string TEMPSAVEPATH = "tempsave";
        /// <summary>
        /// ofd版式文件名称，带文件后缀.ofd,不包含绝对路径，只是文件名称和后缀
        /// </summary>
        string fileName;
        /// <summary>
        /// 是否删除copy到程序路径下的临时ofd文件和其解压的文件夹，默认删除
        /// </summary>
        bool IsDeleteTempFiles = true; 
        /// <summary>
        /// 消息加密后报文
        /// </summary>
        ENCMSGMessage eNCMSGMessage = null;
        /// <summary>
        /// 消息
        /// </summary>
        RetInfo retInfo = null;
        /// <summary>
        /// 运行时间监测1
        /// </summary>
        System.Diagnostics.Stopwatch stopwatch1 = new System.Diagnostics.Stopwatch();

        /// <summary>
        /// json日期时间格式（因存在有yyyy-MM-ddTHH:mm:ss格式）
        /// </summary>
        private IsoDateTimeConverter ISODtCvt = new IsoDateTimeConverter();
        public Form1()
        {
            InitializeComponent();
            //标题栏面板添加鼠标拖动功能
            panel14.MouseDown += Form_MouseDown;
        }
        /// <summary>
        /// 窗口加载时初始化设置
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Load(object sender, EventArgs e)
        {
            lab_Title.Text= lab_Title.Text+"(V"+ System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString() + ")";

            string txt = ExistsWinRar();
            if(string.IsNullOrEmpty(txt))
            {
                MessageBox.Show("电脑上没有WinRar.exe程序。不能使用该软件,请先安装winRar.exe程序后再运行软件");
                this.Close();
            }
            exePath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
            if (!Directory.Exists(exePath + TEMPSAVEPATH))
            {
                Directory.CreateDirectory(exePath + TEMPSAVEPATH);
            }
            string ip = "127.0.0.1";
            string port = "6666";
            //if(!CreateServer(ip,port))
            //{
            //    MessageBox.Show("启动ofd版式发票分析器后台服务器失败");
            //    this.Close();
            //}
        }

        private  string ExistsWinRar()
        {
            string result = string.Empty;

            string key = @"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\WinRAR.exe";
            RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(key);
            if (registryKey != null)
            {
                result = registryKey.GetValue("").ToString();
                registryKey.Close();
            }
            return result;
        }

        /// <summary>
        /// 开启后台服务
        /// </summary>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        private bool CreateServer(string ip, string port)
        {
            if(PortInUse(Int32.Parse(port)))
            {
                MessageBox.Show("端口号" + port + "被占用");
                return false;
            }
            IPAddress ipAddress = IPAddress.Parse(ip);
            return StartServer(ipAddress, port);
        }

        /// <summary>
        /// 端口占用判断
        /// </summary>
        /// <param name="port">端口号</param>
        /// <returns></returns>
        private bool PortInUse(int port)
        {
            bool inUse = false;
            IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();
            IPEndPoint[] ipEndPoints = ipProperties.GetActiveTcpListeners();

            foreach (IPEndPoint endPoint in ipEndPoints)
            {
                if (endPoint.Port == port)
                {
                    inUse = true;
                    break;
                }
            }
            return inUse;
        }

        /// <summary>
        /// 服务Http监听
        /// </summary>
        static HttpListener httpListener1;
        /// <summary>
        /// 服务器状态是否启动成功
        /// </summary>
        static bool _serstatus = false;
        private bool StartServer(IPAddress ipAddress, string port)
        {
            try
            {
                #region//HttpListener
                httpListener1 = new HttpListener();
                string uriPrefix = "";
                //uriPrefix = "http://" + serip + ":" + port + "/" + service + "/";//定义url及端口号,以/结尾
                //uriPrefix = "http://*:" + port + "/" + service + "/";
                uriPrefix = "http://*:" + port + "/";//跨域请求：http://127.0.0.1:8888/crossdomain.xml
                httpListener1.Prefixes.Add(uriPrefix);

                httpListener1.Start();//启动监听器
                /*
                 * 异步监听客户端请求，当客户端的网络请求到来时会自动执行Result委托
                 * 该委托没有返回值，有一个IAsyncResult接口的参数，可通过该参数获取context对象
                 */
                httpListener1.BeginGetContext(Result, null);
                #endregion
                _serstatus = true;
                return true;
            }
            catch (Exception ex)
            {
                _serstatus = false;
                MessageBox.Show("启动HTTP监听服务异常:"+ex.Message);
                return false;
            }
        }

        /// <summary>
        /// 接收异步请求并处理
        /// </summary>
        /// <param name="_iasyncResult"></param>
        private void Result(IAsyncResult _iasyncResult)
        {
            if (httpListener1 == null || !httpListener1.IsListening)
                return;
            //当接收到请求后程序流会走到这里
            var returnByteArr = Encoding.UTF8.GetBytes("");
            httpListener1.BeginGetContext(Result, null);//继续异步监听
            var guid = Guid.NewGuid().ToString();
            var context = httpListener1.EndGetContext(_iasyncResult);//获得context对象
            var request = context.Request;
            var response = context.Response;


            response.ContentType = "application/x-www-form-urlencoded";
            response.ContentType = "application/x-javascript";
            response.AppendHeader("Access-Control-Allow-Origin", "*");
            response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
            response.AddHeader("Access-Control-Allow-Headers", "AuthToken, Authorization, Origin, Content-Type, Accept, X-Requested-With");

            ////如果是js的ajax请求，还可以设置跨域的ip地址与参数
            //context.Response.AppendHeader("Access-Control-Allow-Origin", "*");//后台跨域请求，通常设置为配置文件
            //context.Response.AppendHeader("Access-Control-Allow-Headers", "ID,PW");//后台跨域参数设置，通常设置为配置文件
            //context.Response.AppendHeader("Access-Control-Allow-Method", "post");//后台跨域请求设置，通常设置为配置文件
            //response.ContentType = "text/plain;charset=UTF-8";//告诉客户端返回的ContentType类型为纯文本格式，编码为UTF-8
            response.AddHeader("Content-type", "text/plain");//添加响应头信息
            response.ContentEncoding = Encoding.UTF8;
            if (request.RawUrl == "/crossdomain.xml" || request.RawUrl == "crossdomain.xml")
            {
                string returnmsg = "";
                returnmsg += "<?xml version=\"1.0\"?>";
                returnmsg += "<cross-domain-policy>";
                returnmsg += "<allow-access-from domain=\"*\" />";
                //returnmsg += "<allow-http-httprequest-headers-from domain=\"*\" headers=\"*\" />";
                returnmsg += "</cross-domain-policy>";

                //proConsole.DataContent = new StringBuilder("_接收请求_crossdomain" + "(明文)：" + returnmsg);
                //common.ComWriteLogFile(Common.enumLogLel.一般信息, "", proConsole.DataContent, null);
                ReturnResponse(response, returnmsg);
                return;
            }
            HandleRequest(request, response);//处理客户端发送的请求并返回处理信息
        }
        /// <summary>
        /// 处理http接收的请求
        /// </summary>
        /// <param name="request"></param>
        /// <param name="response"></param>
        private void HandleRequest(HttpListenerRequest httprequest, HttpListenerResponse httpresponse)
        {
            string reqdata = "";//HttpListenerRequest接收到消息
            string retjson = "";//每个业务返回的信息json
            string retdbgjson = "";//每个业务返回的信息json解密明文，debug用
            string base64msg = "";//base64加密字符
            string httpSID = "";//接口规定的sid
            eNCMSGMessage = new ENCMSGMessage();
            retInfo = new RetInfo();
            try
            {
                string RawUrl = "";
                string callback = "";
                string SIDParam = "";
                string SIDName = "";
                string callbackstr = "";
                JObject job = new JObject();
                string StrGuid = Guid.NewGuid().ToString("N");
                #region //接收request请求流并解析参数
                var byteList = new List<byte>();
                var byteArr = new byte[1024 * 5];
                int readLen = 0;
                int len = 0;
                do
                {
                    Thread.Sleep(20);
                    readLen = httprequest.InputStream.Read(byteArr, 0, byteArr.Length);
                    len += readLen;
                    byteList.AddRange(byteArr);
                } while (readLen != 0);
                reqdata = Encoding.UTF8.GetString(byteList.ToArray(), 0, len);

                if (httprequest.HttpMethod == "POST")
                {
                    //HttpUtility属于引用System.Web包下面的类
                    RawUrl = HttpUtility.UrlDecode(reqdata);
                    callback = HttpUtility.ParseQueryString(reqdata).Get("callback");
                    httpSID = HttpUtility.ParseQueryString(reqdata).Get("SID");
                    SIDParam = HttpUtility.ParseQueryString(reqdata).Get("SIDParam");
                }
                else
                {
                    RawUrl = Path.GetFileName(httprequest.RawUrl);
                    callback = httprequest.QueryString["callback"];
                    httpSID = httprequest.QueryString["SID"];
                    SIDParam = httprequest.QueryString["SIDParam"];
                }
                if (RawUrl == "/crossdomain.xml" || RawUrl == "crossdomain.xml")
                {
                    string returnmsg = "";
                    returnmsg += "<?xml version=\"1.0\"?>";
                    returnmsg += "<cross-domain-policy>";
                    returnmsg += "<allow-access-from domain=\"*\" />";
                    //returnmsg += "<allow-http-httprequest-headers-from domain=\"*\" headers=\"*\" />";
                    returnmsg += "</cross-domain-policy>";
                    Console.WriteLine("_接收请求_crossdomain" + "(明文)：" + returnmsg);
                    //proConsole.DataContent = new StringBuilder("_接收请求_crossdomain" + "(明文)：" + returnmsg);
                    //common.ComWriteLogFile(Common.enumLogLel.一般信息, "", proConsole.DataContent, null);
                    ReturnResponse(httpresponse, returnmsg);
                    return;
                }


                try
                {
                    SIDName = (Enum.Parse(typeof(EnumClass.EnumSID), httpSID)).ToString();
                }
                catch
                {
                    Console.WriteLine("_httpSID转换异常，接收请求：" + reqdata);
                    //common.ComWriteLogFile(Common.enumLogLel.异常, "", new StringBuilder("_httpSID转换异常，接收请求：" + reqdata), null);
                }
                callbackstr = callback == null ? "" : ("callback=" + callback + "&");
                Console.WriteLine("_接收请求_" + SIDName + "(密文)：" + callbackstr + reqdata);
                //proConsole.DataContent = new StringBuilder("_接收请求_" + SIDName + "(密文)：" + callbackstr + reqdata);
                //common.ComWriteLogFile(Common.enumLogLel.一般信息, "", proConsole.DataContent, null);
                #endregion

                #region //执行请求并检测执行时间
                stopwatch1 = new System.Diagnostics.Stopwatch();
                stopwatch1.Start();//运行时间监测

                JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
                MyGuid myGuid = new MyGuid();
                if (!string.IsNullOrEmpty(SIDParam))
                {
                    if (SIDParam != "null")
                    {
                        #region
                        reqdata = SIDParam;
                        SIDParam = SIDParam.Replace("_", "+");//反替换
                        SIDParam = SIDParam.Replace("%2B", "+");//反替换(HTML将+替换为了%2B)
                        SIDParam = Base64Helper.DecodeBase64(Encoding.GetEncoding("GB2312"), SIDParam);
                        SIDParam = SIDParam.Replace(Environment.NewLine, "").Replace(Environment.NewLine, "");

                        myGuid = new MyGuid();
                        myGuid = javaScriptSerializer.Deserialize<MyGuid>(SIDParam);
                        //Console.WriteLine(myGuid.StrGuid);
                        if (string.IsNullOrEmpty(myGuid.StrGuid))
                        {
                            myGuid.StrGuid = StrGuid;
                        }
                        job = JsonHelper.JsonToObject(SIDParam);
                        job.Remove("StrGuid");
                        SIDParam = job.ToString();
                        if (SIDParam == "{}")
                        {
                            SIDParam = "{\"SID\":\"" + httpSID + "\",\"StrGuid\":\"" + myGuid.StrGuid + "\"}";
                        }
                        else
                        {
                            job.Add("StrGuid", myGuid.StrGuid);
                            SIDParam = job.ToString();
                        }
                        Console.WriteLine("_接收请求_" + SIDName + "(明文)：" + callbackstr + "&SIDParam=" + SIDParam + "。");
                        //proConsole.DataContent = new StringBuilder("_接收请求_" + SIDName + "(明文)：" + callbackstr + "&SIDParam=" + SIDParam + "。");
                        #endregion
                    }
                    else
                    {
                        SIDParam = "{\"SID\":\"" + httpSID + "\",\"StrGuid\":\"" + StrGuid + "\"}";
                        Console.WriteLine("_接收请求_" + SIDName + "(明文)：" + callbackstr + "&SIDParam=" + SIDParam + "。");
                       // proConsole.DataContent = new StringBuilder("_接收请求_" + SIDName + "(明文)：" + callbackstr + "&SIDParam=" + SIDParam + "。");
                    }
                }
                else
                {
                    SIDParam = "{\"SID\":\"" + httpSID + "\",\"StrGuid\":\"" + StrGuid + "\"}";
                    Console.WriteLine("_接收请求_" + SIDName + "(明文)：" + callbackstr + "&SIDParam=" + SIDParam + "。");
                    //proConsole.DataContent = new StringBuilder("_接收请求_" + SIDName + "(明文)：" + callbackstr + "&SIDParam=" + SIDParam + "。");
                }
                //common.ComWriteLogFile(Common.enumLogLel.一般信息, "", proConsole.DataContent, null);

                #region
                if (!_serstatus)
                {
                    RetInfo retinfo = new RetInfo();
                    retinfo.retcode = ((int)EnumClass.EnumRetCode.失败).ToString();
                    retinfo.retmsg = "_OFD版式发票分析器后台服务未开启。";
                    retjson = JsonConvert.SerializeObject(retinfo, ISODtCvt);
                    Console.WriteLine(retInfo.retmsg);
                    //proConsole.SerMsg = new StringBuilder(retinfo.retmsg);
                }
                else
                {
                    //执行请求
                    Execute(SIDName, SIDParam, StrGuid, javaScriptSerializer, out retjson);
                }
                #endregion


                #region//#if DEBUG//DEBUG查看未加密数据用
#if DEBUG

                retdbgjson = retjson;
                retdbgjson = "此为DEBUG模式，以下为DEBUG模式下返回报文。正式环境下，请运行正式版控制台。" + Environment.NewLine + "ENCMSG:" + retdbgjson;
#else

#endif
                #endregion

                base64msg = Base64Helper.EncodeBase64(Encoding.GetEncoding("GB2312"), retjson);//base64加密
                base64msg = base64msg.Replace("+", "_");//替换+号

                eNCMSGMessage.ENCMSG = base64msg;
                base64msg = JsonConvert.SerializeObject(eNCMSGMessage);//转为json串

                if (!string.IsNullOrEmpty(callback))// 如果CALLBACK不为空，那么就支持JSONP跨域
                {
                    base64msg = callback + Environment.NewLine + "(" + base64msg + ")";
                }
                else// 如果CALLBACK为空，那么执行FLASH跨域
                {
                    base64msg = base64msg;
                }
                Console.WriteLine("_返回报文_" + SIDName + "(密文)：" + base64msg);
                stopwatch1.Stop();//运行时间监测结束
                
                #region//sendResponse//#if DEBUG
#if DEBUG
                ReturnResponse(httpresponse, base64msg + Environment.NewLine + "" + Environment.NewLine + "" + Environment.NewLine + retdbgjson);
#else
                ReturnResponse(httpresponse, base64msg);
#endif
                #endregion

                Console.WriteLine("_返回报文_" + SIDName + "(明文)：用时" + stopwatch1.Elapsed.TotalSeconds + "秒。" + Environment.NewLine + retjson);

                #endregion
            }
            catch (Exception ex)
            {
                #region
                retInfo.SID = httpSID;
                retInfo.retcode = ((int)EnumClass.EnumRetCode.异常).ToString();
                retInfo.retmsg = "请结合接口开发文档验证报文数据是否合法！"
                    + Environment.NewLine + "错误提示：" + ex.Message.ToString()
                    + Environment.NewLine + "故障点：" + ex.StackTrace
                    //+ Environment.NewLine+"故障点：" + ex.StackTrace.Substring(ex.StackTrace.LastIndexOf("\\") + 1, ex.StackTrace.Length - ex.StackTrace.LastIndexOf("\\") - 1)
                    + Environment.NewLine + "接收报文：" + reqdata;
                retjson = JsonConvert.SerializeObject(retInfo);
                Console.WriteLine("_处理请求异常：" + retInfo.retmsg);
                base64msg = Base64Helper.EncodeBase64(Encoding.GetEncoding("GB2312"), retjson);//base64加密
                base64msg = base64msg.Replace("+", "_");//替换+号
                eNCMSGMessage.ENCMSG = base64msg;
                base64msg = JsonConvert.SerializeObject(eNCMSGMessage);//转为json串
                #region//#if DEBUG
#if DEBUG
                ReturnResponse(httpresponse, base64msg + Environment.NewLine + "" + Environment.NewLine + "" + Environment.NewLine + retdbgjson);
#else
                ReturnResponse(httpresponse, base64msg);
#endif
                #endregion
                #endregion
            }
        }

        /// <summary>
        /// 返回结果
        /// </summary>
        /// <param name="httpresponse"></param>
        /// <param name="returnmsg"></param>
        private void ReturnResponse(HttpListenerResponse httpresponse, string returnmsg)
        {
            var returnByteArr = Encoding.UTF8.GetBytes("");
            returnByteArr = Encoding.UTF8.GetBytes(returnmsg);//设置客户端返回信息的编码
            try
            {
                using (var stream = httpresponse.OutputStream)
                {
                    //把处理信息返回到客户端
                    stream.Write(returnByteArr, 0, returnByteArr.Length);
                }
            }
            catch (Exception ex)
            {
                //Console.WriteLine("网络异常：{0}", ex.ToString());
                MessageBox.Show("网络异常："+ex.Message);
            }
        }

        /// <summary>
        /// 执行请求
        /// </summary>
        /// <param name="SIDName"></param>
        /// <param name="SIDParam"></param>
        /// <param name="StrGuid"></param>
        /// <param name="javaScriptSerializer"></param>
        /// <param name="retjson"></param>
        private void Execute(string SIDName, string SIDParam, string StrGuid, JavaScriptSerializer javaScriptSerializer, out string retjson)
        {
            if (SIDName == (EnumClass.EnumSID._0解析ofd版式发票文件).ToString())//1. 解析版式发票文件
            {
                OFDFileIn ofdFileIn = new OFDFileIn();
                Invoice invoice = new Invoice();
                ofdFileIn = javaScriptSerializer.Deserialize<OFDFileIn>(SIDParam);
                ofdFileIn.StrGuid = ((ofdFileIn.StrGuid == null || ofdFileIn.StrGuid == "") ? StrGuid : ofdFileIn.StrGuid);
                invoice.StrGuid = ofdFileIn.StrGuid;
                GetInvoice(ref invoice, ofdFileIn);
                retjson = JsonConvert.SerializeObject(invoice, ISODtCvt);
            }
            else
            {
                RetInfo retInfo = new RetInfo();
                retInfo.retcode = ((int)EnumClass.EnumRetCode.失败).ToString();
                retInfo.retmsg = "异常请求：" + SIDName + "返：" + EnumClass.EnumRetCode.失败.ToString();
                retjson = JsonConvert.SerializeObject(retInfo, ISODtCvt);
                Console.WriteLine(retInfo.retmsg);
            }
        }
        /// <summary>
        /// 将接收到的ofd文件字节流解析成发票
        /// </summary>
        /// <param name="invoice"></param>
        /// <param name="ofdFileIn"></param>
        private void GetInvoice(ref Invoice invoice, OFDFileIn ofdFileIn)
        {
            string selectedFileFullName = ofdFileIn.FileName;
            if (string.IsNullOrEmpty(selectedFileFullName))
            {
                invoice.retcode = "001";
                invoice.retmsg = "请求报文参数FileName不能空";
                return;
            }
            //为控件设置值
            txt_selectedFileFullName.Invoke((MethodInvoker)delegate {
                txt_selectedFileFullName.Text = ofdFileIn.FileName;
            });
            //    SetTxtToControl(txt_selectedFileFullName.Name,ofdFileIn.FileName);
            // txt_selectedFileFullName.Text = ofdFileIn.FileName;
            fileName = ofdFileIn.FileName;
            string fullFileName = exePath + TEMPSAVEPATH + "\\" + fileName;
            //生成本地ofd文件
            SaveFile(ofdFileIn.FileContent,fullFileName);
            //File.Copy(selectedFileFullName, fullFileName, true);
            string unzipDir = exePath + TEMPSAVEPATH + "\\" + fileName.Substring(0,fileName.LastIndexOf('.'));
            //调用winrar.exe进程解压发票
            bool IsSuccess = UnZipFile(fullFileName, unzipDir);
            if (IsSuccess)
            {
                //MessageBox.Show("解压成功");
                VisibleOFDInvoice(ref invoice);
                if (IsDeleteTempFiles)
                    DeleteTempFiles();
            }
            else
            {
                invoice.retcode = "002";
                invoice.retmsg = "在解析ofd文件过程中出错";
            }
        }
        private delegate void SetTxtToControlDelegate(object controlName, object text);
        private void SetTxtToControl(object controlName,object text)
        {
           
        }

        /// <summary>
        /// 根据服务器接收的ofd文件内容字符流（base64加密），生成本地ofd文件
        /// </summary>
        /// <param name="fileContent">服务器接收的ofd文件内容字符流</param>
        /// <param name="fullFileName">保存文件名</param>
        private void SaveFile(string fileContent, string fullFileName)
        {
            string content = Base64Helper.DecodeBase64(Encoding.GetEncoding("GB2312"), fileContent);
            Console.WriteLine(fileContent);
            File.WriteAllText(fullFileName, content);
            //if (File.Exists(fullFileName))
            //    File.Delete(fullFileName);
            //byte[] bytes = Encoding.GetEncoding("GB2312").GetBytes(content);
         
            //using (FileStream s = File.Create(fullFileName,content.Length,FileOptions.RandomAccess))
            //{
            //    s.Write(bytes, 0, bytes.Length);
            //}
        }

        /// <summary>
        /// 选择文件对话框按钮单击事件(废弃)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnImportOFD_Click(object sender, EventArgs e)
        {
            //using (OpenFileDialog of = new OpenFileDialog())
            //{
            //    of.Title = "选择ofd版式发票文件";
            //    of.Filter = "|*.ofd";
            //    if(DialogResult.OK==of.ShowDialog())
            //    {
            //        txt_selectedFileFullName.Text = of.FileName;
            //        destFileName = Path.GetFileName(of.FileName);
            //        destFileName = exePath + TMPSAVEPATH + "\\" + Path.GetFileName(of.FileName);
            //        File.Copy(of.FileName, destFileName, true);
            //    }
            //}
        }

        /// <summary>
        /// 发票解析按钮单击事件  
        /// 1 先弹出选择ofd文件对话框，用户只有选择ofd文件之后才能进行下一步解析
        /// 2 copy选中的ofd文件到可执行文件路径下的tempsave文件夹下，进行解析和读取发票信息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnUnZip_Click(object sender, EventArgs e)
        {
            string selectedFileFullName = string.Empty;
            using (OpenFileDialog of = new OpenFileDialog())
            {
                of.Title = "选择ofd版式发票文件";
                of.Filter = "|*.ofd";
                if (DialogResult.OK == of.ShowDialog())
                {
                    txt_selectedFileFullName.Text = of.FileName;
                    selectedFileFullName = of.FileName;
                }
                else //取消选择ofd文件则不进行解析直接退出
                {
                    return;
                }
            }
            if (string.IsNullOrEmpty(selectedFileFullName))
            {
                MessageBox.Show("请选择要解析的ofd版式发票文件");
                return;
            }
            fileName = Path.GetFileName(selectedFileFullName); 
            string fullFileName= exePath + TEMPSAVEPATH + "\\" + fileName;
            File.Copy(selectedFileFullName, fullFileName, true);
            string unzipDir = exePath + TEMPSAVEPATH + "\\" + Path.GetFileNameWithoutExtension(selectedFileFullName);
            //调用winrar.exe进程解压发票
            bool IsSuccess=UnZipFile(fullFileName, unzipDir);
            if(IsSuccess)
            {
                //MessageBox.Show("解压成功");
                Invoice invoice = null;
                VisibleOFDInvoice(ref invoice);
                if (!cbox_SaveTempFiles.Checked)
                    DeleteTempFiles();
            }
            else
            {
                MessageBox.Show("在解析ofd文件过程中出错");
            }
        }

        /// <summary>
        /// 调用winrar.exe进程解压ofd板式发票文件
        /// </summary>
        /// <param name="rarPathName">ofd版式发票文件路径（包含文件名称和后缀）</param>
        /// <param name="UnPath">解压文件夹路径</param>
        /// <returns></returns>
        private bool UnZipFile(string rarPathName, string UnPath)
        {
            if (!Directory.Exists(UnPath))
                Directory.CreateDirectory(UnPath);
            Process process = new Process();
            ProcessStartInfo startInfo = new ProcessStartInfo();
            startInfo.FileName = "Winrar.exe";
            startInfo.CreateNoWindow = true;
            //x  -ibck -ilog -o+ {0} {1} -y
            string tmpPath = "\"" + rarPathName + "\"";
            string tmpPath2 = "\"" + UnPath + "\"";
            //string winrarLog = Path.GetDirectoryName(rarPathName) + "\\"+"winrarLog.log";
            //if (!File.Exists(winrarLog))
            //    File.Create(winrarLog);
            //winrarLog= "\"" + winrarLog + "\"";
            //string cmd = string.Format(" x  -ibck -ilog{2} -o+ {0} {1} -y", tmpPath,tmpPath2,winrarLog); //覆盖命令( x -o+ 代表覆盖已存在的文件)
            string cmd = string.Format(" x  -ibck -ilog -o+ {0} {1} -y", tmpPath, tmpPath2); //覆盖命令( x -o+ 代表覆盖已存在的文件)
            startInfo.Arguments = cmd;
            process.StartInfo = startInfo;
            bool IsSuccess = false;
            int flag = 0;
            try
            {
                process.Start();
                process.WaitForExit();
               // flag = process.ExitCode;
                //ExitCode==0正常执行；ExitCode≠0 不正常，详细错误码参见winrar.txt文件说明
                if (process.ExitCode == 0)
                {
                    flag = process.ExitCode;
                    process.Close();
                    bool valid = File.Exists(UnPath + "\\" + "OFD.xml") ? true : false;
                    if (!valid)
                    {
                        flag = -1;
                    }
                    else
                    {
                        IsSuccess = true;
                    } 
                }
                else
                {
                    flag=process.ExitCode;
                    process.Close();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            if(IsSuccess )
            {
                if(flag==-1)
                    MessageBox.Show("解压进程返回值为0（成功）,但是解压文件夹下面没有文件OFD.xml，请排查");
            }
            else
            {
                MessageBox.Show("解压进程返回值:"+flag+",请对照WinRarErrCode.txt说明文件错误码查看错误信息");
            }
            return IsSuccess;
        }

        /// <summary>
        /// 提取ofd版式文件发票要素
        /// </summary>
        private void VisibleOFDInvoice(ref Invoice invoice)
        {
            //获取解压ofd文件之后的original_invoice.xml文件，其中保存了发票数据
            string originalInvoicePath = GetOriginalInvoicePath(ref invoice);
            if(!string.IsNullOrEmpty(originalInvoicePath))//成功获取到路径，可以解析发票
            {
                GetFaData(originalInvoicePath,ref invoice);
            }
            else
            {
                if (invoice != null)
                {
                    invoice.retcode = "003";
                    invoice.retmsg = "解析失败";
                }
               
                Console.WriteLine("解析失败,获取发票路径失败");
                MessageBox.Show("解析失败,获取发票路径失败");
            }
        }
        /// <summary>
        /// 获取原始发票数据所在文件的路径 （获取original_invoice.xml发票数据）
        /// </summary>
        /// <returns></returns>
        private string GetOriginalInvoicePath(ref Invoice invoice)
        {
            //ofd板式发票解压后的文件夹路径
            string directoryPath = exePath + TEMPSAVEPATH + "\\" + fileName.Substring(0,fileName.LastIndexOf('.'));
            string tmpPath= directoryPath;
            XmlDocument doc = new XmlDocument();
            XmlNode root = null;
            if (Directory.Exists(directoryPath))
            {
                #region //解析OFD.xml文件
                string file = "OFD.xml";
                if(!File.Exists(tmpPath+"\\"+file))
                {
                    if(invoice!=null)
                    {
                        invoice.retcode = "004";
                        invoice.retmsg = "该文件不符合国家规定的ofd规范，不能解析";
                    }
                    Console.WriteLine("找不到解压路径下的OFD.xml文件");
                    MessageBox.Show("找不到解压路径下的OFD.xml文件");
                    return string.Empty;
                }
                tmpPath = tmpPath + "\\" + file;
                doc.Load(tmpPath);
                root = doc.DocumentElement;
                XmlNamespaceManager nsp = new XmlNamespaceManager(doc.NameTable);
                //将ofd新标准加入命名空间才可以识别前缀ofd元素
                AddNamespace(nsp, root, "ofd");
                string nodeText = XmlHelper.GetSingleNodeText(root, new string[] { "ofd:DocBody/ofd:DocRoot" }, nsp);
                if (string.IsNullOrEmpty(nodeText))
                    return string.Empty;
                PathHelper(ref tmpPath, nodeText);
                #endregion
                #region //解析document.xml文件
                doc.Load(tmpPath);
                root = doc.DocumentElement;
                nodeText = XmlHelper.GetSingleNodeText(root, new string[] { "ofd:Attachments" }, nsp);
                if (string.IsNullOrEmpty(nodeText))
                    return string.Empty;
                PathHelper(ref tmpPath, nodeText);
                #endregion
                #region //解析Attachments.xml
                doc.Load(tmpPath);
                root = doc.DocumentElement;
                nodeText = XmlHelper.GetSingleNodeText(root, new string[] { "ofd:Attachment/ofd:FileLoc" }, nsp);
                if (string.IsNullOrEmpty(nodeText))
                    return string.Empty;
                PathHelper(ref tmpPath, nodeText);
                #endregion
                return tmpPath;
            }
            return "";

        }
        /// <summary>
        /// 为命名空间管理类nsp添加指定前缀名称name的标准
        /// </summary>
        /// <param name="nsp">命名空间管理类</param>
        /// <param name="root">xml根目录，其namespaceurl值为前缀标准</param>
        /// <param name="name">前缀名称</param>
        private void AddNamespace(XmlNamespaceManager nsp, XmlNode root, string name)
        {
            if (string.IsNullOrEmpty(root.NamespaceURI))
            {
                if (root.FirstChild != null && !string.IsNullOrEmpty(root.FirstChild.NamespaceURI))
                    nsp.AddNamespace(name, root.FirstChild.NamespaceURI);
            }
            else
            {
                nsp.AddNamespace(name, root.NamespaceURI);
            }
        }

        /// <summary>
        /// 根据当前路径，以及给定的新文件的路径字符串更新当前路径值，导航到新文件位置
        /// </summary>
        /// <param name="tmpPath">当前路径</param>
        /// <param name="nodeText">给定的新文件的路径字符串</param>
        private void PathHelper(ref string tmpPath,string nodeText)
        {
            string directoryPath= exePath + TEMPSAVEPATH + "\\" + fileName.Substring(0, fileName.LastIndexOf('.'));
            nodeText = nodeText.Replace('/', '\\');
            if (nodeText.StartsWith("\\")) //绝对路径，从解压根目录开始
            {
                tmpPath = directoryPath + nodeText;
            }
            else //相对路径，从当前目录开始
            {
                tmpPath = Path.GetDirectoryName(tmpPath);
                tmpPath = tmpPath + "\\" + nodeText;
            }
        }

        /// <summary>
        /// 发票数据可视化显示在前端页面并保存到数据模型中
        /// </summary>
        /// <param name="path"></param>
        private void GetFaData(string path,ref Invoice invoice)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(path);
            XmlNode root = doc.DocumentElement;
            XmlNode node = null;
            XmlNamespaceManager nsp = new XmlNamespaceManager(doc.NameTable);
            //将前缀名称fp的命名空间加入xml命名空间管理类中
            AddNamespace(nsp, root, "fp");
            //清空前端页面内容项
            ClearAll();
            #region //发票整体票面信息
            #region //数据模型填充
            if(invoice==null)
                invoice = new Invoice();
            invoice.DocID = XmlHelper.GetSingleNodeText(root, new string[] { "fp:DocID" ,"fp:DocId"}, nsp);
            invoice.InvoiceCode= XmlHelper.GetSingleNodeText(root, new string[] { "fp:InvoiceCode" }, nsp);
            invoice.InvoiceNo= XmlHelper.GetSingleNodeText(root, new string[] { "fp:InvoiceNo" }, nsp);
            invoice.TypeCode = XmlHelper.GetSingleNodeText(root, new string[] { "fp:TypeCode" }, nsp);
            invoice.IssueDate= XmlHelper.GetSingleNodeText(root, new string[] { "fp:IssueDate" }, nsp);
            invoice.InvoiceCheckCode = XmlHelper.GetSingleNodeText(root, new string[] { "fp:InvoiceCheckCode" }, nsp);
            invoice.MachineNo= XmlHelper.GetSingleNodeText(root, new string[] { "fp:MachineNo" }, nsp);
            string cipher = XmlHelper.GetSingleNodeText(root, new string[] { "fp:TaxControlCode" }, nsp);
            invoice.TaxControlCode = cipher; //密文
            invoice.BuyerName= XmlHelper.GetSingleNodeText(root, new string[] { "fp:Buyer/fp:BuyerName" }, nsp);
            invoice.BuyerTaxID= XmlHelper.GetSingleNodeText(root, new string[] { "fp:Buyer/fp:BuyerTaxID" }, nsp);
            invoice.BuyerAddrTel= XmlHelper.GetSingleNodeText(root, new string[] { "fp:Buyer/fp:BuyerAddrTel" }, nsp);
            invoice.BuyerFinancialAccount= XmlHelper.GetSingleNodeText(root, new string[] { "fp:Buyer/fp:BuyerFinancialAccount" }, nsp);
            invoice.SellerName = XmlHelper.GetSingleNodeText(root, new string[] { "fp:Seller/fp:SellerName" }, nsp);
            invoice.SellerTaxID= XmlHelper.GetSingleNodeText(root, new string[] { "fp:Seller/fp:SellerTaxID" }, nsp);
            invoice.SellerAddrTel= XmlHelper.GetSingleNodeText(root, new string[] { "fp:Seller/fp:SellerAddrTel" }, nsp);
            invoice.SellerFinancialAccount= XmlHelper.GetSingleNodeText(root, new string[] { "fp:Seller/fp:SellerFinancialAccount" }, nsp);
            invoice.TaxInclusiveTotalAmount= XmlHelper.GetSingleNodeText(root, new string[] { "fp:TaxInclusiveTotalAmount" }, nsp);
            #region //有的没有fp:Note节点
            node = root.SelectSingleNode("fp:Note", nsp);
            invoice.Note = (node == null ? "" : node.InnerXml);
            #endregion
            invoice.InvoiceClerk = XmlHelper.GetSingleNodeText(root, new string[] { "fp:InvoiceClerk" }, nsp); 
            invoice.Payee= XmlHelper.GetSingleNodeText(root, new string[] { "fp:Payee" }, nsp);
            invoice.Checker= XmlHelper.GetSingleNodeText(root, new string[] { "fp:Checker" }, nsp);
            invoice.TaxTotalAmount= XmlHelper.GetSingleNodeText(root, new string[] { "fp:TaxTotalAmount" }, nsp);
            invoice.TaxExclusiveTotalAmount= XmlHelper.GetSingleNodeText(root, new string[] { "fp:TaxExclusiveTotalAmount" }, nsp);
            string qrCodeStr = XmlHelper.GetSingleNodeText(root, new string[] { "fp:GraphCode" }, nsp);
            invoice.GraphCode = qrCodeStr;
            invoice.InvoiceSIA1= XmlHelper.GetSingleNodeText(root, new string[] { "fp:InvoiceSIA1" }, nsp);//如果该字段有内容则是“销项负数”
            invoice.InvoiceSIA2 = XmlHelper.GetSingleNodeText(root, new string[] { "fp:InvoiceSIA2" }, nsp);
            invoice.Signature= XmlHelper.GetSingleNodeText(root, new string[] { "fp:Signature" }, nsp);
            #endregion
            #region  //前端可视化展示
            //Invoice invoice2 = invoice;
            //txt_invoiceCode.Invoke((MethodInvoker)delegate
            //{
            //     txt_invoiceCode.Text = invoice2.InvoiceCode; //无法使用变量
            //});
            //SetTxtToControl(txt_invoiceCode.Name, invoice.InvoiceCode);
            txt_invoiceCode.Text = invoice.InvoiceCode;
            txt_invoiceNo.Text = invoice.InvoiceNo;
            txt_invoiceDate.Text = invoice.IssueDate;
            txt_invoiceCheckCode.Text = invoice.InvoiceCheckCode;
            txt_machineNo.Text = invoice.MachineNo;
            txt_taxControlCode.Text = cipher.Replace("&lt;", "<").Replace("&gt;", ">");
            txt_buyerName.Text = invoice.BuyerName;
            txt_buyerTaxCode.Text = invoice.BuyerTaxID;
            txt_buyerAddressPhone.Text = invoice.BuyerAddrTel;
            txt_buyerBankAccount.Text = invoice.BuyerFinancialAccount;
            txt_sellerName.Text = invoice.SellerName;
            txt_sellerTaxCode.Text = invoice.SellerTaxID;
            txt_sellerAddressPhone.Text = invoice.SellerAddrTel;
            txt_sellerBankAccount.Text = invoice.SellerFinancialAccount;
            txt_taxInclusiveTotalAmount.Text = invoice.TaxInclusiveTotalAmount;
            txt_notes.Text = invoice.Note;
            txt_invoiceClerk.Text = invoice.InvoiceClerk;
            txt_payee.Text = invoice.Payee;
            txt_checker.Text = invoice.Checker;
            txt_taxTotalAmount.Text = invoice.TaxTotalAmount;
            txt_taxExclusiveTotalAmount.Text = invoice.TaxExclusiveTotalAmount;
            if (!string.IsNullOrEmpty(invoice.InvoiceSIA1))
            {
                txt_InvoiceSIA1.Visible = true;
                txt_InvoiceSIA1.Text = invoice.InvoiceSIA1;
            }
                
            GetQRCodeImage(qrCodeStr);//二维码
            #endregion
            #endregion

            #region //发票商品列表明细
            List<GoodsInfo> GoodsInfos = new List<GoodsInfo>();
            XmlNodeList nodeList = root.SelectNodes("fp:GoodsInfos/fp:GoodsInfo", nsp);
            foreach (XmlNode child in nodeList)
            {
                #region //单行商品明细<--->数据模型存储
                GoodsInfo item = new GoodsInfo();
                item.Item = XmlHelper.GetSingleNodeText(child,new string[] { "fp:Item" }, nsp);
                #region //商品明细行的字段fp:Specification,fp:MeasurementDimension,fp:Price,fp:Quantity,都可能没有
                node = child.SelectSingleNode("fp:Specification", nsp);
                item.Specification = (node == null ? "" : node.InnerXml);
                node=child.SelectSingleNode("fp:MeasurementDimension", nsp);
                item.MeasurementDimension = (node == null ? "" : node.InnerXml);
                node = child.SelectSingleNode("fp:Price", nsp);
                item.Price = (node == null ? "" : node.InnerXml);
                node = child.SelectSingleNode("fp:Quantity", nsp);
                item.Quantity = (node == null ? "" : node.InnerXml);
                node = child.SelectSingleNode("fp:Amount", nsp);
                item.Amount = (node == null ? "" : node.InnerXml);
                node = child.SelectSingleNode("fp:TaxScheme", nsp);
                item.TaxScheme = (node == null ? "" : node.InnerXml);
                node = child.SelectSingleNode("fp:TaxAmount", nsp);
                item.TaxAmount = (node == null ? "" : node.InnerXml);
                GoodsInfos.Add(item);
                #endregion
                //item.Specification = XmlHelper.GetSingleNodeText(child, new string[] { "fp:Specification" }, nsp);
                //item.MeasurementDimension = XmlHelper.GetSingleNodeText(child, new string[] { "fp:MeasurementDimension" }, nsp);
                //item.Price = XmlHelper.GetSingleNodeText(child, new string[] { "fp:Price" }, nsp);
                //item.Quantity = XmlHelper.GetSingleNodeText(child, new string[] { "fp:Quantity" }, nsp);
                //item.Amount = XmlHelper.GetSingleNodeText(child, new string[] { "fp:Amount" }, nsp);
                //item.TaxScheme = XmlHelper.GetSingleNodeText(child, new string[] { "fp:TaxScheme" }, nsp);
                //item.TaxAmount = XmlHelper.GetSingleNodeText(child, new string[] { "fp:TaxAmount" }, nsp);
                //GoodsInfos.Add(item);
                #endregion
                #region 可视化显示到页面
                //必须先设置一个项，才能获取剩余项SubItems
                ListViewItem itm = new ListViewItem(item.Item/*XmlHelper.GetSingleNodeText(child, "fp:Item", nsp)*/);
                itm.SubItems.AddRange(new string[] {
                    item.Specification,
                    item.MeasurementDimension,
                    item.Price,
                    item.Quantity,
                    item.Amount,
                    item.TaxScheme,
                    item.TaxAmount
                    //XmlHelper.GetSingleNodeText(child, "fp:Specification", nsp),
                    //XmlHelper.GetSingleNodeText(child, "fp:MeasurementDimension", nsp),
                    //XmlHelper.GetSingleNodeText(child, "fp:Price", nsp),
                    //XmlHelper.GetSingleNodeText(child, "fp:Quantity", nsp),
                    //XmlHelper.GetSingleNodeText(child, "fp:Amount", nsp),
                    //XmlHelper.GetSingleNodeText(child, "fp:TaxScheme", nsp),
                    //XmlHelper.GetSingleNodeText(child, "fp:TaxAmount", nsp)
                });
                listView1.Items.Add(itm);
                #endregion

            }
            invoice.GoodsInfos = GoodsInfos;
            #endregion
        }
        /// <summary>
        /// 清空所有的内容
        /// </summary>
        private void ClearAll()
        {
            #region //发票整体票面信息
            txt_invoiceCode.Clear();
            txt_invoiceNo.Clear();
            txt_invoiceDate.Clear();
            txt_invoiceCheckCode.Clear();
            txt_machineNo.Clear();
            txt_taxControlCode.Clear();
            txt_buyerName.Clear();
            txt_buyerTaxCode.Clear();
            txt_buyerAddressPhone.Clear();
            txt_buyerBankAccount.Clear();
            txt_sellerName.Clear();
            txt_sellerTaxCode.Clear();
            txt_sellerAddressPhone.Clear();
            txt_sellerBankAccount.Clear();
            txt_taxInclusiveTotalAmount.Clear();
            txt_notes.Clear();
            txt_invoiceClerk.Clear();
            txt_payee.Clear();
            txt_checker.Clear();
            txt_taxTotalAmount.Clear();
            txt_taxExclusiveTotalAmount.Clear();
            pictureBox1.Image = null;
            txt_InvoiceSIA1.Clear();
            txt_InvoiceSIA1.Visible = false;
            #endregion
            listView1.Items.Clear();
        }

        /// <summary>
        /// 获取发票二维码
        /// </summary>
        /// <param name="qrCodeStr">二维码信息</param>
        private void GetQRCodeImage(string qrCodeStr)
        {
            // 生成二维码的内容
            //string code = "1,050001700111,35436358,300.00,20200609,14627915136010359375";
            //string strCode = "01,10,011001900211,03108411,4,20200423,11762493383204597018,51B9,";
            //string strCode = "01,10,050001700111,35436358,300.00,20200609,14627915136010359375";
            string[] contents = qrCodeStr.Split(',');
            string strCode = string.Empty;
            bool valid = true; //验证发票二维码内容是否合法
           // int InvoiceCodeIndex = 2; //发票代码内容索引位置
            if("01"!=contents[0])
            {
                string InvoiceType = contents[1]; //发票类型代码 01 普通发票  04 专用发票  10 电子普通发票
                if (InvoiceType.Length == 2)
                {
                    if (contents[1] != "01" || contents[1] != "04" || contents[1] != "10")
                    {
                        MessageBox.Show("该发票二维码不属于增值税普通发票或者专用发票或者电子普通发票");
                        valid = false;
                        return;
                    }
                }
                else
                {
                    //用逗号分割后，第二项内容直接是 发票代码内容（长度10或12位）
                    if (InvoiceType.Length==10 || InvoiceType.Length == 12)
                    {
                    //    InvoiceCodeIndex = 1;
                        strCode = "01,10,"+qrCodeStr.Substring(qrCodeStr.IndexOf(contents[1]));
                    }
                }

            }
            else
            {
                valid = true;
             //   InvoiceCodeIndex = 2;
                strCode = qrCodeStr;
            }
            QRCodeGenerator qrGenerator = new QRCodeGenerator();
            QRCodeData qrCodeData = qrGenerator.CreateQrCode(strCode, QRCodeGenerator.ECCLevel.H);
            QRCode qrcode = new QRCode(qrCodeData);

            // qrcode.GetGraphic 方法可参考下面函数声明
            Bitmap qrCodeImage = qrcode.GetGraphic(2, Color.Black, Color.White, null, 15, 6, false);
           // SetBitmap( qrCodeImage);
            pictureBox1.Image = qrCodeImage;
        }
        private delegate void SetBitmapDelegate(Bitmap qrCodeImage);
        private void SetBitmap( Bitmap qrCodeImage)
        { 
            if (pictureBox1.InvokeRequired)
            {
                SetBitmapDelegate d = new SetBitmapDelegate(SetBitmap);
                d.Invoke( qrCodeImage);
            }
            else
            {
                pictureBox1.Image = qrCodeImage;
            }
        }

        //GetGraphic方法参数说明
        //public Bitmap GetGraphic(int pixelsPerModule, Color darkColor, Color lightColor, Bitmap icon = null, int iconSizePercent = 15, int iconBorderWidth = 6, bool drawQuietZones = true); 
        //int pixelsPerModule:生成二维码图片的像素大小 ，我这里设置的是5 
        //Color darkColor：暗色   一般设置为Color.Black 黑色
        //Color lightColor:亮色   一般设置为Color.White  白色
        //Bitmap icon :二维码 水印图标 例如：Bitmap icon = new Bitmap(context.Server.MapPath("~/images/zs.png")); 默认为NULL ，加上这个二维码中间会显示一个图标
        //int iconSizePercent： 水印图标的大小比例 ，可根据自己的喜好设置 
        //int iconBorderWidth： 水印图标的边框
        //bool drawQuietZones:静止区，位于二维码某一边的空白边界,用来阻止读者获取与正在浏览的二维码无关的信息 即是否绘画二维码的空白边框区域 默认为true

        /// <summary>
        /// 删除copy的ofd临时文件和ofd文件解压后得到的文件夹
        /// </summary>
        private void DeleteTempFiles()
        {
            string filename = exePath + TEMPSAVEPATH + "\\" + fileName;
            if (File.Exists(filename))
            {
                File.Delete(filename);
                string dir = Path.GetDirectoryName(filename) + "\\" + Path.GetFileNameWithoutExtension(filename);
                DeleteTempFolder(dir);
            }
        }

        /// <summary>
        /// 删除文件夹（包括其下的所有文件和子文件夹）
        /// </summary>
        /// <param name="dir">文件夹路径</param>
        private void DeleteTempFolder(string dir)
        {
            if (Directory.Exists(dir))
            {
                string[] fileSystemEntries = Directory.GetFileSystemEntries(dir);
                for (int i = 0; i < fileSystemEntries.Length; i++)
                {
                    string text = fileSystemEntries[i];
                    if (File.Exists(text))
                    {
                        File.Delete(text);
                    }
                    else
                    {
                        DeleteTempFolder(text);
                    }
                }
                Directory.Delete(dir);
            }
        }

        private void cbox_SaveTempFiles_CheckedChanged(object sender, EventArgs e)
        {
            IsDeleteTempFiles = cbox_SaveTempFiles.Checked ? false : true;
        }

        private void btn_Exit_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void btn_Minimize_Click(object sender, EventArgs e)
        {
            this.WindowState = FormWindowState.Minimized;
        }

        public const int WM_SYSCOMMAND = 0x0112;
        public const int SC_MOVE = 0xF010;
        public const int HTCAPTION = 0x0002;
        [DllImport("user32.dll")]
        public static extern bool ReleaseCapture();
        [DllImport("user32.dll")]
        public static extern bool SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);

        //获取鼠标按下时的位置
        private void Form_MouseDown(object sender, MouseEventArgs e)
        {
            ReleaseCapture();
            SendMessage(this.Handle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);
        }
    }
}
